using Xunit;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Reflection;
using System;

namespace LeetCodeQuestionBank.Algorithm
{
    public class No0059_GenerateMatrix
    {
        /*
        给你一个正整数 n ，生成一个包含 1 到 n2 所有元素，且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
        示例 1：
            输入：n = 3
            输出：[[1,2,3],[8,9,4],[7,6,5]]
        示例 2：
            输入：n = 1
            输出：[[1]]
        提示：
            1 <= n <= 20
        */

        public static IEnumerable<object[]> GetTestArgs()
        {
            return new object[][] {
                new object[] { 3, @"[[1,2,3],[8,9,4],[7,6,5]]" },
                new object[] { 1, @"[[1]]" },
            }.MergeFuncNames(new string[] {
                nameof(GenerateMatrix_1),
                nameof(GenerateMatrix_2),
            });
        }

        [Theory]
        [MemberData(nameof(GetTestArgs))]
        public void OnExecute(string funcName, int input, string output)
        {
            Type type = this.GetType();
            MethodInfo methodInfo = type.GetMethod(funcName);
            int[][] methodResult = (int[][])methodInfo.Invoke(this, new object[] { input });
            int[][] rearr = JsonConvert.DeserializeObject<int[][]>(output);
            Assert.Equal(rearr, methodResult);
        }

        /// <summary>
        /// 方法一：模拟
        /// </summary>
        public static int[][] GenerateMatrix_1(int n)
        {
            int maxNum = n * n;
            int curNum = 1;
            int[][] matrix = new int[n][];
            for (int i = 0; i < n; i++)
            {
                matrix[i] = new int[n];
            }
            int row = 0, column = 0;
            int[][] directions = new int[][] {
                new int[] { 0, 1 },
                new int[] { 1, 0 },
                new int[] { 0, -1 },
                new int[] { -1, 0 },
            }; // 右下左上
            int directionIndex = 0;
            while (curNum <= maxNum)
            {
                matrix[row][column] = curNum;
                curNum++;
                int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];
                if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] != 0)
                {
                    directionIndex = (directionIndex + 1) % 4; // 顺时针旋转至下一个方向
                }
                row = row + directions[directionIndex][0];
                column = column + directions[directionIndex][1];
            }
            return matrix;
        }

        /// <summary>
        /// 方法二：按层模拟
        /// </summary>
        public static int[][] GenerateMatrix_2(int n)
        {
            int num = 1;
            int[][] matrix = new int[n][];
            for (int i = 0; i < n; i++)
            {
                matrix[i] = new int[n];
            }
            int left = 0, right = n - 1, top = 0, bottom = n - 1;
            while (left <= right && top <= bottom)
            {
                for (int column = left; column <= right; column++)
                {
                    matrix[top][column] = num;
                    num++;
                }
                for (int row = top + 1; row <= bottom; row++)
                {
                    matrix[row][right] = num;
                    num++;
                }
                if (left < right && top < bottom)
                {
                    for (int column = right - 1; column > left; column--)
                    {
                        matrix[bottom][column] = num;
                        num++;
                    }
                    for (int row = bottom; row > top; row--)
                    {
                        matrix[row][left] = num;
                        num++;
                    }
                }
                left++;
                right--;
                top++;
                bottom--;
            }
            return matrix;
        }
    }
}
